package jmine.tec.web.wicket.pages;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import jmine.tec.persist.PersistMessages;
import jmine.tec.report.impl.ReportBuilder;
import jmine.tec.report.impl.table.ReportTableBuilder;
import jmine.tec.utils.reflection.GenericTypeResolverImpl;
import jmine.tec.web.wicket.component.report.ReportTablePanel;
import jmine.tec.web.wicket.spring.SpringBeanReference;

import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.panel.Panel;

import bancosys.tec.persist.Persistable;
import bancosys.tec.persist.dao.BaseDAOFactory;
import bancosys.tec.persist.exception.PersistenceException;

/**
 * Base para implementação de telas monitores.
 * 
 * @param <BO> BO
 * @author nara.ribeiro
 * @created jan 27, 2012.
 */
public abstract class TableMonitor<BO extends Persistable> extends MonitorTemplate {

    protected final SpringBeanReference<BaseDAOFactory> daoFactoryRef = SpringBeanReference.forName("daoFactory");

    /**
     * Construtor
     */
    public TableMonitor() {
        super();
        this.generateComponents();
    }

    /**
     * Construtor.
     * 
     * @param pageParameters {@link PageParameters}
     */
    public TableMonitor(PageParameters pageParameters) {
        super(pageParameters);

        this.generateComponents();
    }

    /**
     * Gera os principais componentes da página.
     */
    private void generateComponents() {
        Form form = new Form("mainForm");
        this.addComponents(form);
        ReportBuilder reportBuilder = new ReportBuilder(this.getResultFileName(), this.getResultFileName());
        ReportTableBuilder<BO> tableBuilder = reportBuilder.createTableBuilder(this.getEntityClass(), "Monitor");
        this.addResultTableColumns(tableBuilder);
        tableBuilder.setRecords(this.doSearch(this.daoFactoryRef.get()));
        tableBuilder.close();

        Panel panel = new ReportTablePanel("report", reportBuilder.createReport());
        panel.setOutputMarkupId(true);
        panel.setVisible(true);
        form.add(panel);
        this.add(form);
    }

    /**
     * Retorna a classe da entidade que esta sendo manipulada por esta página.
     * 
     * @return a classe da entidade que esta sendo manipulada por esta página
     */
    @SuppressWarnings("unchecked")
    public Class<BO> getEntityClass() {
        try {
            return (Class<BO>) GenericTypeResolverImpl.getInstance().resolveTypeForParameterizedType(
                    (ParameterizedType) this.getClass().getGenericSuperclass(), this.getClass(), 0);
        } catch (IllegalArgumentException e) {
            throw new PersistenceException(PersistMessages.INVALID_BEAN_IMPLEMENTATION.create(this.getClass()));
        }
    }

    /**
     * Retorna uma lista de elementos que serão exibidos na tabela.
     * 
     * @param daoFactory daoFactory
     * @return Lista de elementos a serem exibidos
     */
    protected abstract List<BO> doSearch(BaseDAOFactory daoFactory);

    /**
     * Retorna o nome de arquivo padrão que deve ser utilizado para salvar os arquivos exportados por essa página.
     * 
     * @return O nome de arquivo padrão que deve ser utilizado para salvar os arquivos exportados por essa página
     */
    protected abstract String getResultFileName();

    /**
     * Inclui as colunas que devem ser exibidas na tabela de resultado.
     * 
     * @param table tabela
     */
    protected abstract void addResultTableColumns(ReportTableBuilder<BO> table);

    /**
     * Inclui os componentes no container
     * 
     * @param container container
     */
    protected abstract void addComponents(WebMarkupContainer container);
}
